﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace OmniKits.Windows
{
    public static class VisualTreeUtility
    {
        public static ItemsControl GetItemsControl(this ItemsPresenter self)
        {
            if (self == null) return null;

            DependencyObject parent = self;

            while ((parent = VisualTreeHelper.GetParent(parent)) != null)
            {
                var ic = parent as ItemsControl;
                if (ic != null)
                    return ic;
            }

            return null;
        }

        public static DependencyObject GetTemplatedParent(this FrameworkElement self)
        {
            if (self == null) return null;

            var tp = self.TemplatedParent;
            if (tp != null) return tp;

            return GetTemplatedParent(VisualTreeHelper.GetParent(self) as FrameworkElement);
        }

        public static DependencyObject GetContentParent(this FrameworkElement self)
        {
            if (self == null) return null;

            DependencyObject parent;

            if ((parent = self.Parent) != null)
                return parent;

            if ((parent = self.TemplatedParent) != null)
            {
                if (parent is ItemsPresenter)
                    return parent;

                var cp = parent as ContentPresenter;
                if (cp == null)
                    throw new InvalidOperationException();

                var ip = GetTemplatedParent(cp) as ItemsPresenter;
                if (ip != null)
                    return GetItemsControl(ip);

                return parent;
            }

            return VisualTreeHelper.GetParent(self);
        }

        public static bool IsUserVisible(this FrameworkElement self, FrameworkElement ancestor)
        {
            if (self == null)
                throw new ArgumentNullException(nameof(self));
            if (ancestor == null)
                throw new ArgumentNullException(nameof(ancestor));

            var r = new Rect(0, 0, ancestor.ActualWidth, ancestor.ActualHeight);
            var l = self.TransformToAncestor(ancestor).TransformBounds(new Rect(0,0,self.ActualWidth, self.ActualHeight));
            return r.IntersectsWith(l);
        }

        public static bool IsUserVisible(this FrameworkElement self)
        {
            if (self == null)
                throw new ArgumentNullException(nameof(self));

            var ancestor = self.GetContentParent() as FrameworkElement;
            if (ancestor == null) return false;
            return self.IsUserVisible(ancestor);
        }
    }
}
